package com.zimmor.util;

import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @Author:zimmor
 * @Date: 2021/3/30 9:33
 * @Description
 * @version: 1.0.0
 */

@Component//把webSocketUtil这个对象交给spring来管理
@ServerEndpoint("/websocket/{userid}")//通过这个url来连接服务器
public class WebSocketUtil {
   //存储用户多个终端的WebSocket
   private static Map<String, Set<WebSocketUtil>> userMap = new HashMap<>();
   //记录一个用户有几个设备在线
   private static int countOnline;
   //需要session来对客户发送数据，获取链接特征userId
   private Session session;
   //接收userId
   private String userid;

   /**
    * 当客户端连接到服务器时触发
    * @param session
    * @param userid
    */
   @OnOpen
   public void onOpen(Session session, @PathParam("userid") String userid) {
      this.session = session;
      this.userid = userid;
      //判断当前用户有没有设备在线
      if (userMap.containsKey(userid)) {
         userMap.get(userid).add(this);
         this.addOnlineCount();
         System.out.println(userid + "用户上线了新设备  "+"设备总数:"+this.countOnline);
      } else {
         HashSet<WebSocketUtil> webSockets = new HashSet<>();
         webSockets.add(this);
         userMap.put(userid, webSockets);
         this.addOnlineCount();
         System.out.println(userid + "用户的第一台设备上线  "+"设备总数:"+this.countOnline);
      }
   }

   /**
    * 当客户端关闭连接是触发
    */
   @OnClose
   public void onClose() {
      //如果当前用户的所有设备都下线了，则移除该用户，如果还有在线设备，则移除当前的WebSocket
      if(userMap.get(userid).size() == 0) {
         userMap.remove(userid);
         System.out.println(userid + "用户的所有设备均已下线"+"设备总数:"+this.countOnline);
      } else {
         userMap.get(userid).remove(this);
         this.subOnlineCount();
         System.out.println(userid + "用户已经下线"+"设备总数:"+this.countOnline);
      }
   }

   @OnError
   public void onError(Throwable error) {
      System.out.println("传输发生错误");
      error.printStackTrace();
   }

   /**
    * message 为客户端发送给服务端的信息
    * @param message
    * @param session
    */
   @OnMessage
   public void onMessage(String message, Session session) {
      //判断是否为null
      if (session != null) {
         //如果不为null可以写一些逻辑，比如可以可另一个userid的所有设备全部发送信息
      }
      System.out.println("服务器接收到的"+userid + "信息为:"+message);
      this.sendMessage("服务器收到客户端发送的消息");
   }

   /**
    * 服务器向客户端推送消息
    * @param message
    */
   public boolean sendMessage(String message) {
      try {
         this.session.getBasicRemote().sendText(message);
      } catch (IOException e) {
         System.out.println("发送消息发生异常");
         e.printStackTrace();
         return false;
      }
      return true;
   }

   /**
    * 向在线的的其他用户发送消息
    * @param toUserid
    * @param message
    */
   public void sendToOther(String toUserid, String message) {
      //通过toUserid获取到要发送用户的WebSocket集合,然后向这个userid的所有设备推送消息
      for (WebSocketUtil webSocketUtil : userMap.get(toUserid)) {
         webSocketUtil.sendMessage(message);
      }
      System.out.println("已经向"+toUserid+"用户的所有设备推送了消息");

   }

   /**
    * 获取当前在线的设备数
    * @return
    */
   public int getCountOnline() {
      return this.countOnline;
   }

   /**
    * 上线设备加一
    */
   public synchronized void addOnlineCount() {
      this.countOnline++;
   }

   /**
    * 上线设备减一
    */
   public synchronized void subOnlineCount() {
      this.countOnline--;
   }

}
